MyBatis 与 Spring Boot 的整合

什么是 Spring Boot

Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Boot 致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

Spring Boot 并不是要成为 Spring IO 平台里面众多 “Foundation” 层项目的替代者。Spring Boot 的目标不在于为已解决的问题域提供新的解决方案,而是为平台带来另一种开发体验,从而简化对这些已有技术的使用。对于已经熟悉 Spring 生态系统的开发人员来说,Boot 是一个很理想的选择,不过对于采用 Spring 技术的新人来说,Boot 提供一种更简洁的方式来使用这些技术。

上述描述引用自《深入学习微框架:Spring Boot》一文,该文适合初学者了解学习 Spring Boot。

使用 Spring Boot 集成 Mybatis

和前面的两篇文章《Mybatis 基于 Web 应用的使用》《MyBatis 与 Spring 以及 Spring MVC 的整合》集成的方式相同,这里改用 Spring Boot 来集成。还是使用 Eclipse,需要安装 Spring Tool Suite 插件并创建 Spring Boot 项目,请自行百度,网上教程一抓一大把。

创建项目

新建一个 Spring Boot 项目,完成后的项目结构如下图:
mybatis3
添加 mybatis 和 mysql 的依赖到 pom.xml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lake</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mybatis-spring-boot</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<!-- 为项目的POM文件添加一个父POM -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- devtools 是 boot 的一个热部署工具,当我们修改了 classpath -->
<!-- 下的文件(包括类文件、属性文件、页面等)时,会重新启动应用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- boot 推荐的模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- html 页面解析工具 -->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- apache 工具包 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
</dependencies>
</project>

创建数据库

schema.sql

1
2
3
4
5
6
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) DEFAULT NULL,
`address` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

data.sql

1
2
INSERT INTO `user` (`name`, `address`) VALUES ('Leo', 'GuangDong HuiZhou');
INSERT INTO `user` (`name`, `address`) VALUES ('Dan', 'GuangDong ShanTou');

POJO 类的创建

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.lake.model;
public class User {
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

添加 MyBatis 的配置文件

resources 目录下建立 mybatis.xml 文件,其中定义了 Java 类所对应的别名、数据源和 mapper 文件的位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="User" type="com.lake.model.User" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/lake/mapper/UserMapper.xml" />
</mappers>
</configuration>

其它的 XML 映射配置文件可参见官网

定义 Mapper 接口

定义 Mapper 的 Java 接口,用来访问数据库的接口,其中包括数据库操作的增删查改:

1
2
3
4
5
6
7
8
9
package com.lake.mapper;
import java.util.List;
import com.lake.model.User;
public interface UserMapper {
public User selectUserByID(int id);
}

使用 XML 定义 Mapper

根据已实现的 Mapper 接口,我们需要通过 XML 来给出 Mapper 的实现,通常将 xxxMapper.xml(UserMapper) 文件放在 resources 目录下对应于 Mapper 接口的 com/lake/mapper/ 目录中。

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lake.mapper.UserMapper">
<select id="selectUserByID" parameterType="int" resultType="User">
select * from `user` where id = #{id}
</select>
</mapper>

Mapper XML 文件更加详细的配置信息,参考官网的 Mapper XML 文件版块

通过单例创建 SqlSessionFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.lake.mapper;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class SqlSessionFactoryManager {
private static final String CONFIG_LOCATION = "mybatis.xml";
private static SqlSessionFactory sqlSessionFactory;
// 静态单例模式
public static SqlSessionFactory getSqlSessionFactory() {
if (sqlSessionFactory == null) {
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(CONFIG_LOCATION);
} catch (IOException e) {
e.printStackTrace();
return null;
}
// ** SqlSessionFactoryBuilder 用完即扔
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
return sqlSessionFactory;
}
}

编写 Controller 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.lake.web;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import com.lake.mapper.SqlSessionFactoryManager;
import com.lake.mapper.UserMapper;
@Controller
public class UserController {
@GetMapping("/{id}")
public String showUser(@PathVariable int id, Model model) {
SqlSession sqlSession = SqlSessionFactoryManager.getSqlSessionFactory().openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
model.addAttribute("user", userMapper.selectUserByID(id));
// 返回模板名称
return "user";
} finally {
// TODO: handle finally clause
sqlSession.close();
}
}
}

编写 user.html 页面

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Show User</title>
</head>
<body>
<div class="container">
<div class="id" th:text="${user.id}"></div>
<div class="name" th:text="${user.name}"></div>
<div class="address" th:text="${user.address}"></div>
</div>
</body>
</html>

运行结果

mybatis4

引入 MyBatis-Spring

何为 MyBatis-Spring

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。 使用这个类库中的类,Spring 将会加载必要的 MyBatis 工厂类和 session 类。 这个类库也提供一个简单的方式来注入 MyBatis 数据映射器和 SqlSession 到业务层的 bean 中。而且它也会处理事务,把 MyBatis 的异常转换为 Spring 的 DataAccessException 异常(数据访问异常,译者注)中。最终,它并 不会依赖于 MyBatis,Spring 或 MyBatis-Spring 来构建应用程序代码。

上述描述引用自官网的 mybatis-spring

添加 MyBatis-Spring 依赖

1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>

添加 applicationContext.xml srping 配置文件

resources 目录下建立 applicationContext.xml 文件,其中定义了数据源和 mapper 文件的位置,以及引入了 SqlSessionFactoryBean 来创建 SqlSessionFactory。由于 mybatis 的配置工作转交给 spring 了,因此可以删除 mybatis.xml 的配置文件,如果仍需要在 mybatis 中进行配置,也可保留它并在 sqlSessionFactory bean 下添加 configLocation 属性:

1
2
<!-- configLocation 属性指定 mybatis 的核心配置文件 -->
<property name="configLocation" value="classpath:mybatis.xml" />

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- 采用 DBCP 连接池,需把 DBCP 的 jar 包导入到项目中 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"
p:username="root" p:password="root" p:maxActive="10" p:maxIdle="10">
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- dataSource 属性指定要用到的连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.lake.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
</beans>

Java 添加配置文件

1
2
3
4
5
6
7
8
9
package com.lake.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource(locations = {"classpath:applicationContext.xml"})
public class AppConfig {
}

修改 Controller 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.lake.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import com.lake.mapper.UserMapper;
@Controller
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/{id}")
public String showUser(@PathVariable int id, Model model) {
model.addAttribute("user", userMapper.selectUserByID(id));
return "user";
}
}

这里使用 @Autowired 自动装载 UserMapper,因此也不需要创建 SqlSessionFactory 和 SqlSession 的代码了,可以删除 SqlSessionFactoryManager 这个类。

运行结果

mybatis5

引入 MyBatis Spring Boot Starter

Spring Boot 的 Starter 可以认为是一种方便的依赖描述符,需要集成某种框架或者功能(如集成 JPA、Thymeleaf 或者 MongoDB)时,无需关注各种依赖库的处理,无需具体的配置信息,由 Spring Boot 自动扫描类路径创建所需的 Bean。比如把 spring-boot-starter-data-jpa 的依赖添加到 POM 文件中,就可以方便地使用 JPA 进行数据库访问了。

MyBatis Spring Boot Starter 可以使得使用 MyBatis 变得更加简单:

  • 自动扫描类路径下数据库驱动类,创建 DataSouce 实例
  • 基于 DataSource 自动创建 SqlSessionFactoryBean 实例
  • 自动扫描映射器相关类,生成所需要 Mapper 实例

添加 MyBatis Spring Boot Starter 依赖

1
2
3
4
5
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>

有了这个依赖,MyBatis 和 MyBatis-Spring 的依赖都不再需要,他们会通过 mybatis-spring-boot-starter 间接地引入。

在 application.yml 中添加相关配置

1
2
3
4
5
6
7
8
9
10
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
username: root
password: root
schema: classpath:database/schema.sql
data: classpath:database/data.sql
mybatis:
config-location: classpath:mybatis.xml

由于 Spring Boot 会自动扫描类路径创建所需的 Bean,因此不再需要 applicationContext.xml 和 AppConfig.class 这两个文件了,可以直接删除。

给 Mapper 添加 @Mapper 标注

为了让 Spring Boot 能够自动扫描到 Mapper 类,为其创建 Bean 实例,需给 Mapper 添加 @Mapper 标注。

1
2
3
4
5
6
7
8
9
10
11
package com.lake.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.lake.model.User;
@Mapper
public interface UserMapper {
// @Param 是MyBatis 提供的标注,表示 id 会解析成 SQL 语句(SQL 语句会在 XML 配置或者注解中)的参数。
public User selectUserByID(@Param("id") int id);
}

运行结果

mybatis6

热评文章